﻿using SuperX.Common.Abstract;
using SuperX.Common.Attributes;
using SuperX.Common.BasicService;
using SuperX.Common.Collection;
using SuperX.Common.Helper;
using SuperX.Common.MSG;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using IotRenamedEventArgs = SuperX.Common.MSG.IotRenamedEventArgs;

namespace SuperX.Common.Object
{
    //
    public abstract class BasicObject : DEntityBase, IBasicObject, IJsonSerialize, INotifyPropertyChanged, IDisposable, ICloneable, IRefObject
    {
        // T
        public event EventHandler<MsgEventArgs> NotifyMessage;

        //
        public event EventHandler<IotRenamedEventArgs> Renamed;

        //
        public event PropertyChangedEventHandler PropertyChanged;

        public virtual string ServiceType { get; set; }

        //
        [JsonIgnore]
        public IBasicObject Parent
        {
            get
            {
                return this._parent;
            }
            set
            {
                if (this._parent == value)
                {
                    return;
                }
                if (this.DisableRegister)
                {
                    this._parent = value;
                    return;
                }
                IProjService serverHost = BasicServiceManager.GetProjService();
                IProject project = (serverHost != null) ? serverHost.Project : null;
                if (project == null || project.IsLoading)
                {
                    this._parent = value;
                    return;
                }
                if (!string.IsNullOrEmpty(this.FullName))
                {
                    BasicObject.Remove(this.FullName, this);
                }
                if (this._parent != value)
                {
                    if (this._parent != null)
                    {
                        bool flag = !string.IsNullOrEmpty(this._name);
                    }
                    string fullName = this.FullName;
                    UidResource.RemoveChildGroupObject(this as IObjCollection);
                    this._parent = value;
                    if (_parent != null)
                    {
                        UidResource.AddChildGroupObject(this as IObjCollection);
                        if (!string.IsNullOrEmpty(this.FullName) && this.FullName != fullName)
                        {
                            BasicObject.Add(this.FullName, this);
                        }
                    }
                }
            }
        }

        [TableColumn(ColumnDescription = "全名", IsRequire = true)]
        public virtual string FullName
        {
            get
            {
                if (this.Parent is IObjCollection)
                {
                    IBasicObject parent = this.Parent;
                    if (!string.IsNullOrWhiteSpace((parent != null) ? parent.FullName : null) && !string.IsNullOrWhiteSpace(this.Name))
                    {
                        return this.Parent.FullName + "." + this.Name;
                    }
                }
                return this.Name;
            }
        }

        //
        [JsonIgnore]
        public ObjectStatus ObjectState { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        [TableColumn(ColumnDescription = "名称", IsRequire = true)]
        public virtual string Name
        {
            get
            {
                return this._name;
            }
            set
            {
                if (object.Equals(this._name, value))
                {
                    return;
                }
                if (this.DisableRegister)
                {
                    this._name = value;
                    return;
                }
                if (!(this is IProjService))
                {
                    IProjService serverHost = BasicServiceManager.GetProjService();
                    IProject project = (serverHost != null) ? serverHost.Project : null;
                    if (project == null || project.IsLoading)
                    {
                        this._name = value;
                        BasicObject.ObjectInstances.Add(this);
                        return;
                    }
                }
                if (!(this is IProjService) && !string.IsNullOrEmpty(this._name))
                {
                    IProjService serverHost2 = BasicServiceManager.GetProjService();
                    if (serverHost2 != null)
                    {
                        IProject project2 = serverHost2.Project;
                    }
                    BasicObject.Remove(this.FullName, this);
                }
                if (this.IsValidName(value) && this.IsUniqueName(value, this.Parent as IObjCollection))
                {
                    if (this._parent != null)
                    {
                        bool flag = !string.IsNullOrEmpty(this._name);
                    }
                    string name = this._name;
                    UidResource.RemoveChildGroupObject(this as IObjCollection);
                    this._name = value;
                    UidResource.AddChildGroupObject(this as IObjCollection);
                    this.OnRenamed(name);
                    if (!(this is IProjService))
                    {
                        BasicObject.Add(this.FullName, this);
                    }
                }
            }
        }

        //
        [JsonIgnore]
        public virtual long Identity
        {
            get
            {
                if (this._identity == 0L)
                {
                    this._identity = UidResource.GetUid();
                    UidResource.AddUidObj(this._identity, this);
                }
                return this._identity;
            }
            set
            {
                if (this._identity != value)
                {
                    if (UidResource.GetObjByUid(value) != null)
                    {
                        this._identity = UidResource.GetUid();
                    }
                    else
                    {
                        this._identity = value;
                    }
                    if (this._identity > 0L)
                    {
                        UidResource.AddUidObj(this._identity, this);
                    }
                }
            }
        }

        //
        [JsonIgnore]
        public bool DisableRegister
        {
            get
            {
                return this._disableRegister;
            }
            set
            {
                if (value != this._disableRegister)
                {
                    this._disableRegister = value;
                    if (!this._disableRegister)
                    {
                        BasicObject.Add(this.FullName, this);
                        return;
                    }
                    BasicObject.Remove(this.FullName, this);
                }
            }
        }

        //
        public BasicObject()
        {
            this._disableRegister = ThreadRegisterManager.HasRegister();
        }

        //
        internal static bool Add(string fullName, IBasicObject obj)
        {
            IProjService serverHost = BasicServiceManager.GetProjService();
            IProject project = (serverHost != null) ? serverHost.Project : null;
            if (project == null)
            {
                return false;
            }
            if (!project.Objects.ContainsKey(fullName))
            {
                bool flag = project.Objects.TryAdd(fullName, obj);
                if (flag)
                {
                    project.MsgCache.Listen(obj);
                    IReference references = project.References;
                    if (references == null)
                    {
                        return flag;
                    }
                    references.Listen(obj as IRefObject);
                }
                return flag;
            }
            if (object.Equals(project.Objects[fullName], obj))
            {
                return false;
            }
            if (project.CacheObjects.ContainsKey(fullName))
            {
                project.CacheObjects[fullName].Add(obj);
            }
            else
            {
                project.CacheObjects.TryAdd(fullName, new List<IBasicObject>
                {
                    obj
                });
            }
            return false;
        }

        //
        internal static bool Remove(string fullName, IBasicObject obj)
        {
            IProjService serverHost = BasicServiceManager.GetProjService();
            IProject project = (serverHost != null) ? serverHost.Project : null;
            if (project == null)
            {
                return false;
            }
            if (project.Objects.ContainsKey(fullName))
            {
                bool flag = false;
                if (object.Equals(obj, project.Objects[fullName]))
                {
                    IBasicObject baseObject;
                    flag = project.Objects.TryRemove(fullName, out baseObject);
                    if (flag)
                    {
                        project.MsgCache.UnListen(baseObject);
                        IReference references = project.References;
                        if (references != null)
                        {
                            references.UnListen(baseObject as IRefObject);
                        }
                    }
                }
                if (project.CacheObjects.ContainsKey(fullName) && project.CacheObjects[fullName].Contains(obj))
                {
                    project.CacheObjects[fullName].Remove(obj);
                    if (project.CacheObjects[fullName].Count == 0)
                    {
                        List<IBasicObject> list;
                        project.CacheObjects.TryRemove(fullName, out list);
                    }
                }
                return flag;
            }
            return false;
        }

        //
        private void GetNextUid(bool isCreateNew = false)
        {
            if (isCreateNew || this._identity > 2147483647L || this._identity <= 0L)
            {
                this.Identity = UidResource.GetNextUid(this);
            }
            else
            {
                UidResource.UpdateUid(this.FullName, this._identity);
            }
            UidResource.UpdateSubObjFullNameIdMap(this as IObjCollection);
        }

        [TableColumn(ColumnDescription = "描述", IsRequire = true)]
        public string Description
        {
            get
            {
                return this._description;
            }
            set
            {
                if (this._description != value)
                {
                    this._description = value;
                    this.OnPropertyChanged("Description");
                }
            }
        }

        //
        public virtual object GetPropertyValue(string propertyName)
        {
            return this.GetPropertyValueExtension(propertyName);
        }

        //
        public virtual bool SetPropertyValue(string propertyName, object value)
        {
            return this.SetPropertyValueExtension(propertyName, value);
        }

        //
        public virtual bool IsValidName(string name)
        {
            return NameValidationUtil.IsValidName(name);
        }

        //
        public virtual bool IsUniqueName(string name, IObjCollection parent)
        {
            return parent == null || parent.IsUniqueName(name, null);
        }

        //
        public void OnNotifyMessage(Message msg)
        {
            EventHandler<MsgEventArgs> notifyMessage = this.NotifyMessage;
            if (notifyMessage == null)
            {
                return;
            }
            notifyMessage(this, new MsgEventArgs(msg));
        }

        //
        public void OnRenamed(string oldName)
        {
            EventHandler<IotRenamedEventArgs> renamed = this.Renamed;
            if (renamed == null)
            {
                return;
            }
            renamed(this, new IotRenamedEventArgs(this, oldName));
        }

        //
        public virtual string JsonSerialize()
        {
            return JsonHelper.TransferObjectJsonSerialize(this, true);
        }

        //
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
#if NET40
            if (propertyName == null)
            {
                Trace.WriteLine("propertyName is null");
                StackTrace stackTrace = new StackTrace();
                StackFrame frame = stackTrace.GetFrame(1);
                MethodBase method = frame.GetMethod();
                propertyName = method.Name.Replace("set_", "");
            }
#endif

            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        //
        protected virtual void NotifyPropertyChanged<T>(string propertyName, T propertyValue, T oldPropertyValue, bool isNotifyMessage = true)
        {
            if (object.Equals(propertyValue, oldPropertyValue))
            {
                return;
            }
            PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
            if (propertyChanged == null)
            {
                return;
            }
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        // Token: 0x06000317 RID: 791 RVA: 0x0000609C File Offset: 0x0000429C
        public virtual void Dispose()
        {
            UidResource.RemoveUidObj(this.Identity);
            if (this.PropertyChanged != null)
            {
                foreach (Delegate @delegate in this.PropertyChanged.GetInvocationList())
                {
                    this.PropertyChanged -= (@delegate as PropertyChangedEventHandler);
                }
            }
            if (this.Renamed != null)
            {
                foreach (Delegate delegate2 in this.Renamed.GetInvocationList())
                {
                    this.Renamed -= (delegate2 as EventHandler<IotRenamedEventArgs>);
                }
            }
            if (this.NotifyMessage != null)
            {
                foreach (Delegate delegate3 in this.NotifyMessage.GetInvocationList())
                {
                    this.NotifyMessage -= (delegate3 as EventHandler<MsgEventArgs>);
                }
            }
        }

        //
        public virtual object Clone()
        {
            return base.MemberwiseClone();
        }

        //
        public virtual IBasicObject DeepClone()
        {
            return JsonHelper.JsonDeserialize(JsonHelper.JsonSerialize(this), base.GetType()) as BasicObject;
        }

        //
        public virtual IBasicObject ShallowClone()
        {
            return this.Clone() as BasicObject;
        }

        //
        private long _identity;

        //
        private string _name;

        //
        private IBasicObject _parent;

        //
        private string _description = string.Empty;

        //
        private bool _disableRegister;

        //
        protected static ConcurrentList<IBasicObject> ObjectInstances = new ConcurrentList<IBasicObject>();
    }
}